<?php
/**
 * Created by PhpStorm.
 * User: wuchao
 * Date: 2020/6/3
 * Time: 15:50
 */

namespace app\api\controller\v1\home;

use app\middleware\ApiAuth;
use think\Request;
use think\facade\Db;

class Pay
{
    protected $middleware = [ApiAuth::class];

    /**JsApi支付
     * @return mixed
     * @throws \WxPayException
     */
    public function JsApi(Request $request)
    {
        require_once '../sdk/WxpayAPI/lib/WxPay.Config.php';
        require_once '../sdk/WxpayAPI/lib/WxPay.Api.php';
        require_once '../sdk/WxpayAPI/example/WxPay.JsApiPay.php';
        $mastr_order_no = $request->param('mastr_order_no');//主订单编号
        $openid = $request->param('openid');//openidID
        $type = $request->param('type');//1:微信 2：余额
        if (empty($mastr_order_no)) return jsonFail('缺少订单号');
        if (empty($openid)) return jsonFail('缺少openid');
        if (empty($type)) return jsonFail('缺少参数');
        $order_list = Db::table('order')->alias('a')
            ->join('goods b', 'a.goods_id = b.id')
            ->field('a.total_price,b.name,a.user_id')
            ->where('a.mastr_order_no', $mastr_order_no)->select()->toArray();
        if (empty($order_list)) return jsonFail('订单数据错误');
        $total_back = 0;
        $title = '';
        $user_id = '';
        foreach ($order_list as $v) {
            $user_id = $v['user_id'];
            $total_back += $v['total_price'];
            $title .= $v['name'] . '|';
        }
        if ($type == 2) {//余额支付时
            Db::startTrans();
            $dec = Db::table('user')->where('id', $user_id)
                ->dec('integral', $total_back)
                ->update();
                $res = Db::table('order')->where('mastr_order_no', $mastr_order_no)->update(['is_pay'=>1,'pay_type'=>1]);
            if ($dec != 0 && $res !=0) {
                Db::commit();
                return jsonSuccess('余额支付成功');
            } else {
                Db::rollback();
                return jsonFail('余额支付失败');
            }
        } else if ($type == 1) {//微信支付时
            $money = $total_back * 100;
            if ($money == 0) return jsonFail('系统金额出错');
            $tools = new \JsApiPay();
            $input = new \WxPayUnifiedOrder();
            //$input->profit_sharing("Y");//是否需要分账，Y:N
            $input->SetBody($title);//商品描述
            $input->SetAttach($title); //附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用
            $input->SetOut_trade_no($mastr_order_no);//商户订单号
            $input->SetTotal_fee($money);//订单金额
            $input->SetTime_start(date("YmdHis"));//交易起始时间
            $input->SetTime_expire(date("YmdHis", time() + 600));//交易结束时间
            $input->SetGoods_tag("test"); //订单优惠标记，使用代金券或立减优惠功能时需要的参数，实际上这里可以不要
            $input->SetNotify_url("http://sxbiz.jlxmall.com/api/v1/Notify");//接收回调通知地址
            $input->SetTrade_type("JSAPI"); //支付类型
            $input->SetOpenid($openid);//用户openid
            $order = \WxPayApi::unifiedOrder($input);//统一下单，该方法中包含了签名算法
            $jsApiParameters = $tools->GetJsApiParameters((array)$order);
            //统一下单参数
            //将统一下单接口生成的预支付订单参数返回给前端，前端就可以调取支付了
            return jsonSuccess('操作成功', json_decode($jsApiParameters, true));//getBack是我自定义的方法，就是给前端ajax请求返回json格式数据，1代表成功，这里你要自己修改。
        }
    }

    /**微信退款
     * @param Request $request
     */
    public function refund(Request $request)
    {
        require_once '../sdk/WxpayAPI/lib/WxPay.Config.php';
        require_once '../sdk/WxpayAPI/lib/WxPay.Api.php';
        require_once '../sdk/WxpayAPI/example/WxPay.JsApiPay.php';
        $mastr_order_no = $request->param('mastr_order_no');//主订单编号
        $back_reason = $request->param('back_reason');//退款原因
        if (empty($mastr_order_no) || empty($back_reason)) return jsonFail('缺少参数');
        $order_list = Db::table('order')->alias('a')
            ->join('goods b', 'a.goods_id = b.id')
            ->field('a.user_id,a.pay_type,a.id,a.goods_id,a.num,a.status,a.pid_price,a.is_pay,a.pid,a.total_price,a.transaction_id,b.name,a.is_believe')
            ->where('a.mastr_order_no', $mastr_order_no)->select()->toArray();
        if (empty($order_list)) return jsonFail('订单数据错误');
        $total_back = 0;
        Db::startTrans();
        $order_ids = array_column($order_list, 'id');
        foreach ($order_list as $v) {
            $user_id = $v['user_id'];
            $pay_type = $v['pay_type'];
            $is_believe = $v['is_believe'];
            $is_pay = $v['is_pay'];
            $pid = $v['pid'];
            $pid_price = $v['pid_price'];
            $transaction_id = $v['transaction_id'];
            $total_back += $v['total_price'];
            if ($v['status'] > 0) return jsonFail('该订单已出库,暂不支持退款');
            $red = Db::execute("update goods  set stock=stock+{$v['num']},ice_stock = ice_stock-{$v['num']}  where id={$v['goods_id']}");
            if ($red == false) {
                Db::rollback();
                return jsonFail('减少库存失败', $red);
            }
        }
        $user = Db::table('user')->where('id', $user_id)->find();
        if ($is_pay == 0) {//未支付订单
            $res = Db::table('order')->where('mastr_order_no', $mastr_order_no)->update(['status' => -4, 'back_time' => time(),
                'back_reason' => $back_reason,
                'back_money' => Db::raw('total_price')]);
            foreach ($order_ids as $v) {
                $red = Db::table('order_status')->insertGetId([
                    'oid' => $v,
                    'change_message' => '订单已被用户取消订单',
                    'create_time' => time(),
                    'name' => $user['name'],
                    'phone' => $user['phone'],
                    'role_type' => $user['role_type'] == 1 ? '老板' : '员工',
                ]);
            }
            if ($res != 0) {
                Db::commit();
                return jsonSuccess('取消成功');
            } else {
                Db::rollback();
                return jsonFail('取消失败');
            }
        } else if ($pay_type == 1) {//余额支付时
            $res = Db::table('order')->where('mastr_order_no', $mastr_order_no)->update(['status' => -4, 'back_time' => time(),
                'back_reason' => $back_reason,
                'back_money' => Db::raw('total_price')]);
            foreach ($order_ids as $v) {
                $red = Db::table('order_status')->insertGetId([
                    'oid' => $v,
                    'change_message' => '余额支付订单已被用户退款',
                    'create_time' => time(),
                    'name' => $user['name'],
                    'phone' => $user['phone'],
                    'role_type' => $user['role_type'] == 1 ? '老板' : '员工',
                ]);
            }
            if ($res != 0 && $red != 0) {
                $dec = Db::table('user')->where('id', $user_id)
                    ->dec('integral', $total_back)
                    ->update();
                if ($dec != 0) {
                    Db::commit();
                    return jsonSuccess('余额成功');
                } else {
                    Db::rollback();
                    return jsonFail('余额退款失败');
                }
            } else {
                Db::rollback();
                return jsonFail('取消失败');
            }
        }
        $money = $total_back * 100;
        $merchid = \WxPayConfig::MCHID;
        $input = new \WxPayRefund();
        $input->SetOut_trade_no($mastr_order_no);   //自己的订单号
        $input->SetTransaction_id($transaction_id);  //微信官方生成的订单流水号，在支付成功中有返回
        $input->SetOut_refund_no(create_order_no());   //退款单号
        $input->SetTotal_fee($money);   //订单标价金额，单位为分
        $input->SetRefund_fee($money);   //退款总金额，订单总金额，单位为分，只能为整数
        $input->SetOp_user_id($merchid);
        $result = \WxPayApi::refund($input); //退款操作
        try {
            if (($result['return_code'] == 'SUCCESS') && ($result['result_code'] == 'SUCCESS')) {
                $res = Db::table('order')->where('mastr_order_no', $mastr_order_no)->update(['status' => -3, 'back_time' => time(),
                    'back_reason' => $back_reason,
                    'company_price' => 0,
                    'primary_price' => 0,
                    'driver_price' => 0,
                    'pid_price' => 0,
                    'back_money' => Db::raw('total_price')
                ]);
                foreach ($order_ids as $v) {
                    $red = Db::table('order_status')->insertGetId([
                        'oid' => $v,
                        'change_message' => '微信支付订单已被用户退款',
                        'create_time' => time(),
                        'name' => $user['name'],
                        'phone' => $user['phone'],
                        'role_type' => $user['role_type'] == 1 ? '老板' : '员工',
                    ]);
                }
                if ($pid != 0) {//有上级
                    Db::table('user')->where('id', $pid)
                        ->dec('integral', $pid_price['pid_price'])
                        ->update();
                }
                if ($res != 0) {
                    Db::commit();
                    return jsonSuccess('退款成功');
                } else {
                    Db::rollback();
                    return jsonFail('退款失败');
                }
            } else {
                //退款失败
                Db::rollback();
                return jsonFail($result);
            }
        } catch (\Exception $e) {
            Db::rollback();
            return jsonFail($e->getMessage());
        }
    }

    /**回调处理
     * @param Request $request
     */
    public function notify()
    {
        header('Content-Type:text/json;charset=utf-8');
        echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        ini_set('date.timezone', 'Asia/Shanghai');
        error_reporting(E_ERROR);
        //初始化日志
        require_once '../sdk/WxpayAPI/lib/WxPay.Config.php';
        $xml = $this->postdata();
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $obj = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        ksort($obj);
        $str = $this->ToUrlParams($obj);
        $string = $str . "&key=" . \WxPayConfig::KEY;
        $user_sign = strtoupper(md5($string));
        if ($user_sign == $obj['sign']) {
            try {
                //验证成功
                $order = $obj['out_trade_no'];//订单号
                $userid = $obj['openid'];//用户id
                $attach = $obj['attach'];//商品名称
                $money = $obj['total_fee'] / 100;//金额
                $transaction_id = $obj['transaction_id'];//微信支付订单号
                $data = Db::table('order')->where('mastr_order_no', $order)->field('id,pid,pid_price,goods_id,num')->select()->toArray();
                foreach ($data as $v) {
                    $res = Db::table('goods')->where('id', $v['goods_id'])->update(['sales' => Db::raw("sales + {$v['num']}"),
                    ]);
                    if ($v['pid'] != 0) {//有上级
                        Db::table('user')->where('id', $v['pid'])
                            ->inc('integral', $v['pid_price'])
                            ->update();
                    }
                    $res = Db::table('order_status')->insertGetId([
                        'oid' => $v['id'],
                        'change_message' => '订单已支付，等待出库',
                        'create_time' => time(),
//                        'name'=>$user['name'],
//                        'phone'=>$user['phone'],
//                        'role_type' => $user['role_type'] == 1 ? '老板' : '员工',
                    ]);
                }
                $res = Db::table('order')->where('mastr_order_no', $order)->update([
                    'is_pay' => 1, 'pay_time' => time(), 'transaction_id' => $transaction_id,
                ]);
            } catch (\Exception $e) {
                file_put_contents('/opt/www/sxb/api/runtime/payerror.txt', json_encode($e->getMessage()), FILE_APPEND);
            }
        }
    }

    /**微信退款
     * @param Request $request
     */
    public function RefundOptions(Request $request)
    {
        $admin_id = $request->param('admin_id');//运营商ID
        $type = $request->param('type');//1:取消订单 2：申请退款
        if (empty($admin_id) || empty($type)) return jsonFail('缺少参数');
        $data = Db::table('refund_options')->where('admin_id', $admin_id)->where('type', $type)->select()->toArray();
        return jsonSuccess('获取成功', $data);
    }

    /*
     * 接收post数据
    */
    public function postdata()
    {
        $receipt = file_get_contents("php://input");
        return $receipt;
    }

    /**
     * 格式化参数格式化成url参数
     */
    public function ToUrlParams($value)
    {
        $buff = "";
        foreach ($value as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }
}